package com.douqu.game.core.entity.battle;

import com.bean.core.buffer.ByteBuffer;
import com.douqu.game.core.config.battle.MonsterConfig;
import com.douqu.game.core.config.card.CardConfig;
import com.douqu.game.core.config.challenge.CardParamConfig;
import com.douqu.game.core.config.map.CityArmyConfig;
import com.douqu.game.core.config.map.CityArmyGroupConfig;
import com.douqu.game.core.config.sprite.MasterConfig;
import com.douqu.game.core.config.sprite.MasterParamConfig;
import com.douqu.game.core.e.E_Attribute;
import com.douqu.game.core.entity.EntityObject;
import com.douqu.game.core.entity.Player;
import com.douqu.game.core.entity.activity.MatchBaseInfo;
import com.douqu.game.core.entity.db.CardDB;
import com.douqu.game.core.entity.world.map.SpriteExpeditionBean;
import com.douqu.game.core.entity.world.map.SpriteGarrisonBean;
import com.douqu.game.core.factory.DataFactory;
import com.douqu.game.core.util.LogUtils;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @Author: Bean
 * @Description:
 * @Date: 2017-12-06 14:17
 */
public class BattleTemp extends EntityObject {

    /**
     * 如果是玩家的时候表示是玩家流水号
     * 是关卡或者什么官阶的时候是其它信息组合而成的字符串
     */
    private String indexInfo;
    /**
     * 昵称
     */
    private String masterName;

    /**
     * 只有在阵营匹配的时候才有这个对象
     */
    private MatchBaseInfo baseInfo;

    /**
     * 获得的星级
     */
    private int star;

    /**
     * 主将数据
     */
    private SpriteTemp master;

    /**
     * 士兵数据
     */
    private List<SpriteTemp> soldierList = new CopyOnWriteArrayList<>();

//    /**
//     * 添加时间
//     */
//    private long addTime;

    private long maxTotalHp;

    public void writeTo(ByteBuffer buffer){
        master.writeTo(buffer);
        buffer.writeInt(soldierList.size());
        for (SpriteTemp temp:soldierList){
            temp.writeTo(buffer);
        }
    }

    public void loadForm(ByteBuffer buffer){
        master = new SpriteTemp();
        master.loadFrom(buffer);
        int size = buffer.readInt();
        soldierList = new CopyOnWriteArrayList<>();
        for (int i = 0;i < size; i++){
            SpriteTemp temp = new SpriteTemp();
            temp.loadFrom(buffer);
            soldierList.add(temp);
        }
    }

    public BattleTemp()
    {
        master = new SpriteTemp();
    }

    public BattleTemp(Player player, double masterHPRate, double armyHPRate)
    {
        indexInfo = player.getObjectIndex();
        MasterConfig masterConfig = DataFactory.getInstance().getGameObject(DataFactory.MASTER_KEY, player.master);
        int hp = masterConfig.getAttribute(E_Attribute.HP.getCode(), player.getLv(), player.getMasterExtraAddAttributes(E_Attribute.HP.getCode()));
        master = new SpriteTemp(player.master, player.getLv(), (long) (hp * masterHPRate), hp, hp, 0);
        CardConfig cardConfig = null;
        for(CardDB cardDB : player.getWorldMapCardList())
        {
            hp = cardDB.getAttribute(E_Attribute.HP.getCode());
            cardConfig = cardDB.getConfig();
            for(int i = 0; i < cardConfig.soldierCount; i++)
            {
                addSoldierTemp(new SpriteTemp(cardDB.id, cardDB.getLv(), (long) (hp * armyHPRate), hp, hp, SpriteTemp.IGNORE_INDEX), true);
            }
        }

        LogUtils.debug("重新初始化后的BattleTemp -> " + this);
    }

    public BattleTemp(SpriteGarrisonBean spriteGarrisonBean)
    {
        indexInfo = spriteGarrisonBean.getObjectIndex();

        CityArmyConfig cityArmyConfig = DataFactory.getInstance().getGameObject(DataFactory.CITY_ARMY_KEY, spriteGarrisonBean.armyId);
        CityArmyGroupConfig cityArmyGroupConfig = DataFactory.getInstance().getGameObject(DataFactory.CITY_ARMY_GROUP_KEY, spriteGarrisonBean.groupId);
        MasterParamConfig masterParamConfig = DataFactory.getInstance().getGameObject(DataFactory.MASTER_PARAM_KEY, cityArmyGroupConfig.getLv());
        MonsterConfig monsterConfig = DataFactory.getInstance().getGameObject(DataFactory.MONSTER_KEY, cityArmyConfig.monsterId);
        long hp = Long.parseLong(masterParamConfig.getVariable(E_Attribute.HP.getMsg()));
        master = new SpriteTemp(cityArmyConfig.master, cityArmyGroupConfig.getLv(), hp, hp, hp, 0);
        List<CardDB> battleCardList = new CopyOnWriteArrayList<>();
        //获取怪物属性配置
        int[] cardParam;
        boolean isNullCardParam = monsterConfig.isNullCardParam();
        int cardParamId;
        CardConfig cardConfig;
        CardDB cardDB;
        for (int i =0;i<monsterConfig.cards.length;i++){
            cardConfig = monsterConfig.cards[i];
            cardDB = new CardDB(cardConfig.id);
            cardDB.init();
            if (!isNullCardParam)
            {
                cardParamId =monsterConfig.cardParam[i];
                CardParamConfig cardParamConfig = DataFactory.getInstance().getGameObject(DataFactory.CARD_PARAM_KEY, cardParamId);
                cardParam= cardParamConfig.cardParams;
                cardDB.setMonsterData(cardParam);
                cardDB.setExtAttr(cardParamConfig.paraments);
            }
            else {
                cardParam=  cityArmyGroupConfig.monsterLv;
                cardDB.setMonsterData(cardParam);
                cardDB.setExtAttr(cityArmyGroupConfig.paraments);
            }
            battleCardList.add(cardDB);
        }
        int index = 0;
        for(CardDB cardDBs : battleCardList)
        {
            hp = cardDBs.getAttribute(E_Attribute.HP.getCode());
            cardConfig = cardDBs.getConfig();
            for(int i = 0; i < cardConfig.soldierCount; i++)
            {

                addSoldierTemp(new SpriteTemp(cardDBs.id, cardDBs.getLv(), hp, hp, hp, index++), true);
                //LogUtils.info("ADD 守军++++++++id="+cardDBs.id+" lv="+cardDBs.getLv()+" hp="+hp+" index ="+index);
            }
        }
    }

    public BattleTemp(SpriteExpeditionBean spriteExpeditionBean)
    {
        indexInfo = spriteExpeditionBean.getObjectIndex();

        CityArmyConfig cityArmyConfig = DataFactory.getInstance().getGameObject(DataFactory.CITY_ARMY_KEY, spriteExpeditionBean.armyId);
        CityArmyGroupConfig cityArmyGroupConfig = DataFactory.getInstance().getGameObject(DataFactory.CITY_ARMY_GROUP_KEY, spriteExpeditionBean.groupId);
        MasterParamConfig masterParamConfig = DataFactory.getInstance().getGameObject(DataFactory.MASTER_PARAM_KEY, cityArmyGroupConfig.getLv());
        MonsterConfig monsterConfig = DataFactory.getInstance().getGameObject(DataFactory.MONSTER_KEY, cityArmyConfig.monsterId);
        long hp = Long.parseLong(masterParamConfig.getVariable(E_Attribute.HP.getMsg()));
        master = new SpriteTemp(cityArmyConfig.master, cityArmyGroupConfig.getLv(), hp, hp, hp, 0);
        List<CardDB> battleCardList = new CopyOnWriteArrayList<>();

        //获得怪物属性配置
        int[] cardParam;
        boolean isNullCardParam = monsterConfig.isNullCardParam();
        CardConfig cardConfig;
        CardDB cardDB;
        for (int i =0;i<monsterConfig.cards.length;i++){
            cardConfig = monsterConfig.cards[i];
            cardDB = new CardDB(cardConfig.id);
            cardDB.init();
            if (!isNullCardParam)
            {
                int cardParamId =monsterConfig.cardParam[i];
                CardParamConfig cardParamConfig = DataFactory.getInstance().getGameObject(DataFactory.CARD_PARAM_KEY, cardParamId);
                cardParam= cardParamConfig.cardParams;
                cardDB.setMonsterData(cardParam);
                cardDB.setExtAttr(cardParamConfig.paraments);
            }
            else{
                cardParam= cityArmyGroupConfig.monsterLv;
                cardDB.setMonsterData(cardParam);
                cardDB.setExtAttr(cityArmyGroupConfig.paraments);
            }
            battleCardList.add(cardDB);
        }
        int index = 0;
        for(CardDB cardDBs : battleCardList)
        {
            hp = cardDBs.getAttribute(E_Attribute.HP.getCode());
            cardConfig = cardDBs.getConfig();
            for(int i = 0; i < cardConfig.soldierCount; i++)
            {
                addSoldierTemp(new SpriteTemp(cardDBs.id, cardDBs.getLv(), hp, hp, hp, index++), true);
            }
        }
    }

    public void full()
    {
        master.setHp(master.getMaxHp());
        master.setCacheMaxHp(master.getMaxHp());

        for(SpriteTemp spriteTemp : soldierList)
        {
            spriteTemp.setHp(spriteTemp.getMaxHp());
            spriteTemp.setCacheMaxHp(spriteTemp.getMaxHp());
        }
    }

    public void addHp(double addPercent)
    {
        if(master.getHp() > 0 && master.getHp() != master.getMaxHp()){
            long hp = (long)(master.getHp() + master.getMaxHp() * addPercent);
            hp = hp >= master.getMaxHp() ? master.getMaxHp() : hp;
            master.setHp(hp);
        }

        soldierList.stream().filter(v -> v.getHp() > 0 && v.getHp() != v.getMaxHp()).forEach(v ->{
            long hp = (long)(v.getHp() + v.getMaxHp() * addPercent);
            hp = hp >= v.getMaxHp() ? v.getMaxHp() : hp;
            v.setHp(hp);
        });
    }

    public boolean isFull()
    {
        if(master.getHp() < master.getMaxHp())
            return false;

        for(SpriteTemp spriteTemp : soldierList)
        {
            if(spriteTemp.getHp() < spriteTemp.getMaxHp())
                return false;
        }

        return true;
    }

    /**
     * 所有活着的卡牌和主角是否满血(不计算死亡)
     * @return
     */
    public boolean isFullByLive()
    {
        int percent = getPercent();
        return percent == 100 ? true : false;
    }

    public boolean cardHasDie(){
        for(SpriteTemp spriteTemp : soldierList)
        {
            if(spriteTemp.getHp() <= 0 ){
                return true;
            }
        }
        return false;   }

    public void revive(double percent){
        for(SpriteTemp spriteTemp : soldierList)
        {
            if(spriteTemp.getHp() <= 0){
                spriteTemp.setHp((long)(spriteTemp.getMaxHp() * percent));
            }
        }
    }

    /**
     * 算出血量百分比(不计算死亡)
     * @return
     */
    public int getPercent(){
        long totalHP = master.getHp();
        long totalMaxHP = master.getMaxHp() ;

        for(SpriteTemp spriteTemp : soldierList)
        {
            if(spriteTemp.getHp() <= 0 ){
                continue;
            }
            totalHP += spriteTemp.getHp();
            totalMaxHP += spriteTemp.getMaxHp();
        }
        return totalHP == totalMaxHP ? 100 : (int)((double)totalHP / totalMaxHP * 100);
    }

    public int getMasterHPRate()
    {
        double temp = (double)master.getHp() / master.getMaxHp() * 100;
        int result = (int) temp;
        if(result == 0 && temp > 0)
            return 1;

        return result;
    }


    public int getArmyHPRate()
    {
        if(soldierList.isEmpty())
            return 0;

        long totalHP = 0, totalMaxHP = 0;
        for(SpriteTemp spriteTemp : soldierList)
        {
            totalHP += spriteTemp.getHp();
            totalMaxHP += spriteTemp.getMaxHp();
        }

        double temp = (double)totalHP / totalMaxHP * 100;
        int result = (int) temp;
        if(result == 0 && temp > 0)
            return 1;

        return result;
    }

    public void die()
    {
        master.setHp(0);
        for(SpriteTemp spriteTemp : soldierList)
        {
            spriteTemp.setHp(0);
        }
    }

    public void addSoldierTemp(SpriteTemp spriteTemp, boolean merge)
    {
        if(merge)
        {
            boolean isIn = false;
            for(SpriteTemp temp : soldierList)
            {
                if(temp.getId() == spriteTemp.getId() && temp.getIndex() == spriteTemp.getIndex())
                {
                    isIn = true;
                    temp.merge(spriteTemp);
                    break;
                }
            }
            if(!isIn)
                soldierList.add(spriteTemp);
        }
        else
        {
            soldierList.add(spriteTemp);
        }
    }

//    public boolean isOverdue(long currentTime)
//    {
//        return addTime > 0 && currentTime - addTime >= 240000;
//    }

    public long getMaxTotalHp(){
        if(maxTotalHp == 0){
            for(SpriteTemp spriteTemp : soldierList)
            {
                maxTotalHp += spriteTemp.getMaxHp();
            }
            maxTotalHp += master.getMaxHp();
        }
        return maxTotalHp;
    }

    public long getCurrentTotalHp()
    {
        return getTotalArmyHP() + master.getHp();
    }

    public String getHpInfo()
    {
        return (getTotalArmyHP() + master.getHp()) + "/" + (getTotalArmyMaxHP() + master.getMaxHp());
    }


    /**
     * 军团当前血量总和
     * @return
     */
    public long getTotalArmyHP()
    {
        long currentTotalHp = 0;
        for(SpriteTemp spriteTemp : soldierList)
        {
            currentTotalHp += spriteTemp.getHp();
        }
        return currentTotalHp;
    }

    /**
     * 军团血量上限总和(包括死亡)
     * @return
     */
    public long getTotalArmyMaxHP()
    {
        long currentTotalMaxHp = 0;
        for(SpriteTemp spriteTemp : soldierList)
        {
            currentTotalMaxHp += spriteTemp.getMaxHp();
        }
        return currentTotalMaxHp;
    }

    /**
     * 军团血量上限总和(不包括死亡)
     * @return
     */
    public long getTotalArmyMaxHPByLive()
    {
        long currentTotalMaxHp = 0;
        for(SpriteTemp spriteTemp : soldierList)
        {
            if(spriteTemp.getHp() <= 0)
                continue;
            currentTotalMaxHp += spriteTemp.getMaxHp();
        }
        return currentTotalMaxHp;
    }



    /**
     * 获取伤害值
     * @return
     */
    public long getTotalDamage(){
        long offsetHp = 0;
        for(SpriteTemp spriteTemp : soldierList)
        {
            offsetHp += spriteTemp.getToEnemyDamage();
        }
        offsetHp += master.getToEnemyDamage();
        return offsetHp;
    }


    public long getSoldierHP(int id)
    {
        for(SpriteTemp spriteTemp : soldierList)
        {
            if(spriteTemp.getId() == id)
                return spriteTemp.getHp();
        }

        return 0;
    }

    public SpriteTemp getSpriteTemp(int id, int index)
    {
        for(SpriteTemp spriteTemp : soldierList)
        {
            if(index != SpriteTemp.IGNORE_INDEX)
            {
                if(spriteTemp.getId() == id && spriteTemp.getIndex() == index)
                    return spriteTemp;
            }
            else
            {
                if(spriteTemp.getId() == id)
                    return spriteTemp;
            }
        }

        return null;
    }

    public String getHPStr(int id)
    {
        for(SpriteTemp spriteTemp : soldierList)
        {
            if(spriteTemp.getId() == id)
                return spriteTemp.getHp() + "/" + spriteTemp.getMaxHp();
        }
        return "";
    }

    public List<SpriteTemp> getSoldierList() {
        return soldierList;
    }

    public String getIndexInfo() {
        return indexInfo;
    }

    public void setIndexInfo(String indexInfo) {
        this.indexInfo = indexInfo;
    }

    public int getStar() {
        return star;
    }

    public void setStar(int star) {
        this.star = star;
    }

    public SpriteTemp getMaster() {
        return master;
    }

    public void setMaster(SpriteTemp master) {
        this.master = master;
    }

    public void setSoldierList(List<SpriteTemp> soldierList) {
        this.soldierList = soldierList;
    }

    public MatchBaseInfo getBaseInfo() {
        return baseInfo;
    }

    public void setBaseInfo(MatchBaseInfo baseInfo) {
        this.baseInfo = baseInfo;
    }

    public String getMasterName() {
        return masterName;
    }

    public void setMasterName(String masterName) {
        this.masterName = masterName;
    }


    @Override
    public String toString() {
        return "{" +
                "indexInfo='" + indexInfo + '\'' +
                ", master=" + master +
                ", soldierList=" + soldierList +
                "} ";
    }
}
